package infostroy.bookagolf.components.panels;

import infostroy.bookagolf.common.Constants.Colors;
import infostroy.bookagolf.common.Constants.Dimensions;
import infostroy.bookagolf.common.Constants.Icons;
import infostroy.bookagolf.common.Constants.Sizes;
import infostroy.bookagolf.common.helpers.ImageHelper;

import javax.swing.*;
import javax.swing.border.EmptyBorder;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.image.BufferedImage;

public abstract class GolfPanelWithSlider extends GolfBasePanel {

	private JLayeredPane layeredPane = new JLayeredPane();

	private JPanel slidePanel = new GolfSlidePanel();
	private JPanel contentPanel = new JPanel();
	private JButton slideButton = new GolfSliderButton();

	private boolean isMinimized = false;

	public GolfPanelWithSlider() {
		this.setLayout(new BoxLayout(this, BoxLayout.LINE_AXIS));
		this.setBackground(Color.WHITE);
		this.setBorder(new EmptyBorder(0, Sizes.GAP_BETWEEN_TABS_AND_CONTENT,
				0, 0));
		initList();
		initMembers();
		initSlidePanel();
		initContentPanel();
	}

	private void initSlidePanel() {
		addSlidePanelComponents(slidePanel);
		this.add(slidePanel);
	}

	protected abstract void addSlidePanelComponents(JPanel panel);

	private void initContentPanel() {
		slideButton.setBounds(0, 120, slideButton.getMaximumSize().width,
				slideButton.getMaximumSize().height);

		contentPanel.setBackground(Colors.CONTENT_PANEL_BACKGROUND);
		contentPanel.setOpaque(true);
		contentPanel.setBounds(0, 0, Dimensions.CONTENT_PANEL_DIM.width,
				Dimensions.CONTENT_PANEL_DIM.height);

		addContentPanelComponents(contentPanel);

		layeredPane.add(contentPanel, new Integer(0));
		layeredPane.add(slideButton, new Integer(1));
		this.add(layeredPane);
	}

	protected abstract void addContentPanelComponents(JPanel panel);

	protected abstract void initList();
	
	/**
	 * Init class components like buttons, labels and so on here.
	 */
	protected abstract void initMembers();
	
	protected void changeVisibility(boolean visible, JPanel container) {
		for (Component component : container.getComponents()) {
			component.setVisible(visible);
		}
	}

	protected void resizeChildren(int sliderPanel, JComponent pane,
			JLayeredPane parent) {
		pane.setBounds(0, 0, parent.getParent().getWidth() - sliderPanel,
				pane.getHeight());
		for (Component component : pane.getComponents()) {
			component.setPreferredSize(new Dimension(pane.getWidth(), component
					.getHeight()));
			component.revalidate();
		}
	}

	public boolean isMinimized() {
		return isMinimized;
	}

	public void setMinimized(boolean isMinimized) {
		this.isMinimized = isMinimized;
	}

	public JPanel getContentPanel() {
		return contentPanel;
	}

    private class GolfSliderButton extends JButton implements ActionListener {
        private BufferedImage image;
        private Timer timer;

		private GolfSliderButton() {
			super();
			image = ImageHelper.getInstance().loadImage(
					Icons.SLIDE_PANEL_BUTTON);
			setIcon(new ImageIcon(image));
			setOpaque(false);
			setBorderPainted(false);
			setFocusPainted(false);
			this.addActionListener(this);
		}

		@Override
		public Dimension getMinimumSize() {
			return new Dimension(image.getWidth(), image.getHeight());
		}

		@Override
		public Dimension getPreferredSize() {
			return new Dimension(image.getWidth(), image.getHeight());
		}

		@Override
		public Dimension getMaximumSize() {
			return new Dimension(image.getWidth(), image.getHeight());
		}

		@Override
		public void actionPerformed(ActionEvent e) {
			this.setEnabled(false);
			if (isMinimized()) {
				changeVisibility(true, slidePanel);
			} else {
				changeVisibility(false, slidePanel);
			}
			timer = new Timer(25, new PanelHideListener(this));
			timer.start();
		}
	}

	private class PanelHideListener implements ActionListener {
        private int counter;
        private int width;

        private final JButton source;

        public PanelHideListener(JButton source) {
            this.source = source;
            if (isMinimized()) {
                this.width = Sizes.SLIDE_PANEL_MIN_WIDTH;
            } else {
                this.width = Sizes.SLIDE_PANEL_MAX_WIDTH;
            }
            counter = 8;
        }

		@Override
		public void actionPerformed(ActionEvent e) {
			if (isMinimized()) {
				width += 20;
			} else {
				width -= 20;
			}
			resize(e);
		}

		private void resize(ActionEvent e) {
			if (counter == 0) {
				source.setEnabled(true);
				if (!isMinimized()) {
					setMinimized(true);
					slidePanel
							.setBounds(Sizes.GAP_BETWEEN_TABS_AND_CONTENT, 0,
									Sizes.SLIDE_PANEL_MIN_WIDTH,
									slidePanel.getHeight());
					slidePanel
							.setMaximumSize(new Dimension(
									Sizes.SLIDE_PANEL_MIN_WIDTH, slidePanel
											.getHeight()));
				} else {
					setMinimized(false);
					slidePanel
							.setBounds(Sizes.GAP_BETWEEN_TABS_AND_CONTENT, 0,
									Sizes.SLIDE_PANEL_MAX_WIDTH,
									slidePanel.getHeight());
					slidePanel
							.setMaximumSize(new Dimension(
									Sizes.SLIDE_PANEL_MAX_WIDTH, slidePanel
											.getHeight()));
				}

				layeredPane.setBounds(slidePanel.getWidth()
						+ Sizes.GAP_BETWEEN_TABS_AND_CONTENT, 0,
						layeredPane.getMaximumSize().width,
						layeredPane.getMaximumSize().height);
				resizeChildren(slidePanel.getWidth()
						+ Sizes.GAP_BETWEEN_TABS_AND_CONTENT, contentPanel,
						layeredPane);
				((Timer) e.getSource()).stop();
			} else if (counter > 0) {
				slidePanel.setBounds(Sizes.GAP_BETWEEN_TABS_AND_CONTENT, 0,
						width, slidePanel.getHeight());
				slidePanel.setMaximumSize(new Dimension(width, slidePanel
						.getHeight()));

				layeredPane.setBounds(slidePanel.getWidth()
						+ Sizes.GAP_BETWEEN_TABS_AND_CONTENT, 0,
						layeredPane.getMaximumSize().width,
						layeredPane.getMaximumSize().height);
				resizeChildren(slidePanel.getWidth()
						+ Sizes.GAP_BETWEEN_TABS_AND_CONTENT, contentPanel,
						layeredPane);
				counter--;
			}
		}
	}

}
